package com.ruoyi.car.business.service.impl;

import java.io.InputStream;
import java.util.*;

import com.github.pagehelper.PageHelper;
import com.ruoyi.car.business.domain.BusBpmnInfo;
import com.ruoyi.car.business.domain.BusCarPackageAudit;
import com.ruoyi.car.business.domain.BusServiceItem;
import com.ruoyi.car.business.mapper.BusCarPackageAuditMapper;
import com.ruoyi.car.business.query.CarPackageAuditQuery;
import com.ruoyi.car.business.service.IBusBpmnInfoService;
import com.ruoyi.car.business.service.IBusCarPackageAuditService;
import com.ruoyi.car.business.service.IBusServiceItemService;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TablePageInfo;
import com.ruoyi.common.exception.business.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.system.service.ISysUserService;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.text.Convert;
import org.springframework.transaction.annotation.Transactional;

/**
 * 【请填写功能名称】Service业务层处理
 * 
 * @author ruoyi
 * @date 2022-02-04
 */
@Service
public class BusCarPackageAuditServiceImpl implements IBusCarPackageAuditService
{
    @Autowired
    private BusCarPackageAuditMapper busCarPackageAuditMapper;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private IBusBpmnInfoService bpmnInfoService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private IBusServiceItemService serviceItemService;
    @Autowired
    private TaskService taskService;

    /**
     * 查询【请填写功能名称】
     * 
     * @param id 【请填写功能名称】主键
     * @return 【请填写功能名称】
     */
    @Override
    public BusCarPackageAudit selectBusCarPackageAuditById(Long id)
    {
        return busCarPackageAuditMapper.selectBusCarPackageAuditById(id);
    }

    /**
     * 查询【请填写功能名称】列表
     * 
     * @param busCarPackageAudit 【请填写功能名称】
     * @return 【请填写功能名称】
     */
    @Override
    public List<BusCarPackageAudit> selectBusCarPackageAuditList(BusCarPackageAudit busCarPackageAudit)
    {
        return busCarPackageAuditMapper.selectBusCarPackageAuditList(busCarPackageAudit);
    }

    /**
     * 新增【请填写功能名称】
     * 
     * @param busCarPackageAudit 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int insertBusCarPackageAudit(BusCarPackageAudit busCarPackageAudit)
    {
        busCarPackageAudit.setCreateTime(DateUtils.getNowDate());
        return busCarPackageAuditMapper.insertBusCarPackageAudit(busCarPackageAudit);
    }

    /**
     * 修改【请填写功能名称】
     * 
     * @param busCarPackageAudit 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int updateBusCarPackageAudit(BusCarPackageAudit busCarPackageAudit)
    {
        return busCarPackageAuditMapper.updateBusCarPackageAudit(busCarPackageAudit);
    }

    /**
     * 批量删除【请填写功能名称】
     * 
     * @param ids 需要删除的【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteBusCarPackageAuditByIds(String ids)
    {
        return busCarPackageAuditMapper.deleteBusCarPackageAuditByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除【请填写功能名称】信息
     * 
     * @param id 【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteBusCarPackageAuditById(Long id)
    {
        return busCarPackageAuditMapper.deleteBusCarPackageAuditById(id);
    }

    @Override
    public TablePageInfo<BusCarPackageAudit> query(CarPackageAuditQuery qo) {
        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        List<BusCarPackageAudit> carPackageAudits = busCarPackageAuditMapper.selectForList(qo);
        for (BusCarPackageAudit audit : carPackageAudits) {
            //方案一:在数据库中进行连表查询
            //方案二:进行单表查询,程序中遍历的时候,再去查询用户的信息(基本不变,可以放入缓存中)
            // 关联查询用户的名称,audit.getCreator()-->获取数据库存储当前创建人id
            // 在遍历过程中,调用userService,根据id获取到用户队形,然后可以获取到用户的名称,设置到creator属性中
            // 前台展示的,看到的是用户名称
            audit.setCreator(userService.selectUserById(Long.parseLong(audit.getCreator())).getUserName());
            if(audit.getAuditorId()!=null){
                audit.setAuditorName(userService.selectUserById(audit.getAuditorId()).getUserName());
            }
        }
        return new TablePageInfo<BusCarPackageAudit>(carPackageAudits);
    }

    @Override
    public InputStream getProcessImg(Long id) {
        InputStream inputStream = null;
        // 根据id查询CarPackageAudit对象
        BusCarPackageAudit audit = this.selectBusCarPackageAuditById(id);
        Long bpmninfoId = audit.getBpmninfoId();
        // 查询BpmnInfo对象
        BusBpmnInfo bpmnInfo = bpmnInfoService.selectBusBpmnInfoById(bpmninfoId);
        // 可以通过bpmnInfo获取流程定义id
        // 判断流程是否正在进行中,如果正在进行中,需要高亮节点,如果已经结束,只需要看到流程图,不需要高亮节点
        BpmnModel bpmnModel = repositoryService.getBpmnModel(bpmnInfo.getActProcessId());
        List<String> highLightedActivities = null;
        if(BusCarPackageAudit.STATUS_IN_ROGRESS.equals(audit.getStatus())){
            // 流程正在流转,查找当前节点,高亮当前节点
            highLightedActivities = runtimeService.getActiveActivityIds(audit.getInstanceId());
        }else {
            // 流程已经结束,不需要高亮节点
            highLightedActivities = Collections.EMPTY_LIST;
        }
        DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        // generateDiagram(bpmn模型,需要高亮节点id集合,需要高亮连线id集合)
        inputStream = generator.generateDiagram(bpmnModel, highLightedActivities, Collections.EMPTY_LIST,
                "宋体", "宋体", "宋体");
        return inputStream;
    }

    @Override
    @Transactional
    public void cancelApply(Long id) {
        // 合理性校验
        BusCarPackageAudit audit = this.selectBusCarPackageAuditById(id);
        if (!BusCarPackageAudit.STATUS_IN_ROGRESS.equals(audit.getStatus())) {
            throw new BusinessException("非法操作");
        }
        // 更新CarPackageAudit对象状态
        busCarPackageAuditMapper.changeStatus(id,BusCarPackageAudit.STATUS_CANCEL);
        //审核撤销的时候,需要把当前审核人字段设置为空
        busCarPackageAuditMapper.setAuditor(id,null);
        // 更新ServiceItem的状态
        serviceItemService.changeStatus(audit.getServiceItemId(), BusServiceItem.AUDITSTATUS_INIT);
        // 删除流程实例
        runtimeService.deleteProcessInstance(audit.getInstanceId(), "撤销审核");
    }

    @Override
    @Transactional
    public void audit(Long id, int auditStatus, String info) {
        // 进行合理化校验
        BusCarPackageAudit carPackageAudit = this.selectBusCarPackageAuditById(id);
        if(carPackageAudit==null || !BusCarPackageAudit.STATUS_IN_ROGRESS.equals(carPackageAudit.getStatus())){
            // 处于审核中的记录才能进行审核
            throw new BusinessException("只有处于审核状态的记录才能进行审核操作");
        }
        // 获取流程实例目前的任务   根据流程实例id查询活动节点
        Task currentTask = taskService.createTaskQuery().processInstanceId(carPackageAudit.getInstanceId()).singleResult();
        // 完成任务设置流程变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("auditStatus",auditStatus);
        taskService.complete(currentTask.getId(),variables);
        //判断同意还是拒绝
        if(BusCarPackageAudit.STATUS_PASS.equals(auditStatus)){
            // 同意
            // 判断是否有下一个节点
            Task nextTask = taskService.createTaskQuery()
                    .processInstanceId(carPackageAudit.getInstanceId()).singleResult();
            if(nextTask==null){
                //流程结束了
                carPackageAudit.setStatus(BusCarPackageAudit.STATUS_PASS);//状态修改为通过
                carPackageAudit.setAuditorId(null);// 设置当前审核人为空
                //修改serviceItem的状态
                serviceItemService.changeStatus(carPackageAudit.getServiceItemId(),BusServiceItem.AUDITSTATUS_APPROVED);
            }else{
                //流程还没结束
                carPackageAudit.setAuditorId((Long.parseLong(nextTask.getAssignee())));//设置审核对象中当前审核人id设置下一个节点处理人
            }
        }else{
            //审核拒绝
            carPackageAudit.setStatus(BusCarPackageAudit.STATUS_REJECT);//状态修改为拒绝状态
            carPackageAudit.setAuditorId(null);// 设置当前审核人为空
            //修改serviceItem的状态
            serviceItemService.changeStatus(carPackageAudit.getServiceItemId(),BusServiceItem.AUDITSTATUS_REPLY);
        }
        SysUser currentUser = ShiroUtils.getSysUser();
        carPackageAudit.setAuditTime(new Date());//设置审核时间
        carPackageAudit.setAuditUserIds(carPackageAudit.getAuditUserIds()+"["+currentUser.getUserId()+"],");
        String infoStr =BusCarPackageAudit.STATUS_PASS.equals(auditStatus)?"同意":"拒绝";
        carPackageAudit.setInfo(carPackageAudit.getInfo()+"<br>"+currentUser.getUserName()+infoStr+",批注:"+info );
        this.updateForAudit(carPackageAudit);
    }

    private void updateForAudit(BusCarPackageAudit carPackageAudit) {
        busCarPackageAuditMapper.updateForAudit(carPackageAudit);
    }
}
